//只有main.cpp文件允许include该头文件

#include"../include/utils.h"
#include"../user.module/dbuser.h"
#include"../cmd.module/cmd.h"
#include"../right.module/sql_grant.h"
#include"../view.module/sql_view.h"
#include"../MetaST.module/MetaType.h"
#include"../PagerMM.module/PageManager.h"
#include"../TableMM.module/PagePool.h"
#include"../SavenDB.inner/tbcore.h"
#include"../SavenDB.inner/test_table.h"
#include"../index.module/sql_index.h"



#include<stdio.h>
#include<iostream>
#include<string>
#include<sstream>
#include<vector>

// extern DBUser::UserChecker sys_UserChecker;


//当前全局用户名称
std::string cur_user = "root";

//全局视图协调器
Viewer::ViewKeeper sys_ViewKeeper;

//全局索引协调器
DBIndex::IndexKeeper sys_IndexKeeper;

//系统事务控制核心
TBCore::SavenDB_TBCore sysCheckerCore;


//系统用户权限管理器-自动初始化并读取文件
DBUser::UserChecker sys_UserChecker;



//系统帮助信息
void showSysInfo(){
    printf("Welcome SavenDB DBMS!\n");
    printf("Created by SavenNeer for SDUST IOT DB-class-design\n");
}


void showSysHelp(){
    printf("[relogin;] Switch user in runtime.\n");
    printf("[exit] Exit system when you at longin-UI.\n");
}


/* 提取操作对象名称 */

//select语句
//成功0 失败-1
int pick_select(const std::string line,DBUser::UserChecker& ck){
    std::vector<std::string> rhs;
    rhs.clear();
    std::stringstream ss(line);
    std::string one = "";
    std::vector<std::string> res = SavenUtils::RegexSearch(line,"select\\s.+?from\\s[a-zA-Z0-9,\\_]+");
    int lenth = res.size();
    if(lenth == 0){
        return -1;
    }
    for(int k=0;k<res.size();k++){
        //开始分析名称
        one = res[k];
        one = SavenUtils::trim(SavenUtils::Split_second(one,"from")) + ",";
        //循环拆解
        for(int i=0;i<100;i++){
            std::string pt = SavenUtils::trim(SavenUtils::Split_first(one,","));
            if(pt == "")break;
            rhs.push_back(pt);
            one = SavenUtils::trim(SavenUtils::Split_second(one,","));
            if(one == "")break;
        }
    }
    //去重
    std::sort(rhs.begin(),rhs.end());
    rhs.erase(std::unique(rhs.begin(),rhs.end()),rhs.end());
    //输出表名称结果
    lenth = rhs.size();
    if(lenth == 0){
        return -1;
    }
    printf("[select]:table_names=");
    for(int i=0;i<lenth;i++){
        printf(" %s",rhs[i].c_str());
    }
    printf("\n");
    //
    int flag = 1;
    for(int i=0;i<lenth;i++){
        std::string tbname = rhs[i];
        if(ck.admit(cur_user,tbname,"select")){
            //
        }else{
            flag = 0;
            break;
        }
    }
    if(flag == 0){
        printf("[error]-no select right\n");
        return -1;
    }
    return 0;
}


//update语句
//成功0 失败-1
int pick_update(const std::string line,DBUser::UserChecker& ck){
    std::vector<std::string> rhs;
    std::stringstream ss(line);
    std::string one = "";
    std::vector<std::string> res = SavenUtils::RegexSearch(line,"(?<=update)\\s+[a-zA-Z0-9\\_]+");
    int lenth = res.size();
    if(lenth == 0){
        return -1;
    }
    printf("[update]:table_name=%s\n",res[0].c_str());
    //检查权限
    if(ck.admit(cur_user,res[0],"update")){
        //
    }else{
        printf("[error]-no update right\n");
        return -1;
    }
    return 0;
}


//delete语句
//成功0 失败-1
int pick_delete(const std::string line,DBUser::UserChecker& ck){
    std::vector<std::string> rhs;
    std::stringstream ss(line);
    std::string one = "";
    std::vector<std::string> res = SavenUtils::RegexSearch(line,"(?<=delete from)\\s+[a-zA-Z0-9\\_]+");
    int lenth = res.size();
    if(lenth == 0){
        return -1;
    }
    printf("[delete]:table_name=%s\n",res[0].c_str());
    //检查权限
    if(ck.admit(cur_user,res[0],"delete")){
        //
    }else{
        printf("[error]-no delete right\n");
        return -1;
    }
    return 0;
}



//insert语句
//成功0 失败-1
int pick_insert(const std::string line,DBUser::UserChecker& ck){
    std::vector<std::string> rhs;
    std::stringstream ss(line);
    std::string one = "";
    std::vector<std::string> res = SavenUtils::RegexSearch(line,"(?<=insert into)\\s+[a-zA-Z0-9\\_]+");
    int lenth = res.size();
    if(lenth == 0){
        return -1;
    }
    printf("[insert]:table_name=%s\n",res[0].c_str());
    //检查权限
    if(ck.admit(cur_user,res[0],"insert")){
        //
    }else{
        printf("[error]-no insert right\n");
        return -1;
    }
    return 0;
}


//create table/view/index判断
//返回需要生成的对象的名称与类型的字符串
int pick_create(const std::string line,DBUser::UserChecker& ck,std::string& objname,std::string& objtype){
    std::string order = SavenUtils::trim(line);
    std::vector<std::string> res = SavenUtils::RegexSearch(order,
    "create\\s+(view|table|index)\\s+([a-zA-Z0-9\\_]+)");
    // printf("res.size() = %d\n",(int)res.size());
    // for(int i=0;i<res.size();i++){
    //     printf("res.=[%s]\n",res[i].c_str());
    // }
    if(res.size() == 0){
        return -1;
    }
    std::stringstream ss(res[0]);
    //    create  table/view/index name
    ss >> objtype >> objtype >> objname;
    // objname = res[1];
    // objtype = res[0];//(view|table|index)
    printf("[create]:[%s]->[%s]\n",objname.c_str(),objtype.c_str());
    // //要求用户权限管理器添加新的系统账户及其相关权限
    // //将视图和基本表的权限合而为一管理
    // ck.setNewTableWithRights(cur_user,objname);
    return 0;
}

//drop table/view/index判断
//返回被drop对象的名称与类型的字符串
int pick_drop(const std::string line,DBUser::UserChecker& ck,std::string& objname,std::string& objtype){
    std::string order = SavenUtils::trim(line);
    std::vector<std::string> res = SavenUtils::RegexSearch(order,"drop\\s+(view|table|index)\\s+([a-zA-Z0-9\\_]+)");
    if(res.size() == 0){
        return -1;
    }
    std::stringstream ss(res[0]);
    ss >> objtype >> objtype >> objname;
    // objname = res[1];
    // objtype = res[0];//(view|table|index)
    printf("[create]:%s->%s\n",objname.c_str(),objtype.c_str());
    // //删除系统中该表的存在性
    // ck.delOneTable(cur_user,objname);
    return 0;
}

const std::string dataPath = "../data/database.tb";

//获取表信息
int getTableInfo(const std::string objname){
    int ret = sysCheckerCore.getInfo(dataPath,objname);
    if(ret == 0){
        printf("[sys]-Nothing...\n");
        return -1;
    }
    TableUI::TextTable pt;
    TableUI::convertTextTable(sysCheckerCore.res,pt);
    std::cout << pt;
    return 0;
}


//sql执行器
//正确0 错误-1
int sysRun(const std::string order,int outer){
    sysCheckerCore.check(dataPath,order);
    if(outer == 1){
        TableUI::TextTable pt;
        TableUI::convertTextTable(sysCheckerCore.res,pt);
        std::cout << pt;
    }
    return sysCheckerCore.inner_ret;
}

void help_database(){
    //展示所有的表
    printf("Table in System:");
    std::vector<std::string> alltbname = sysCheckerCore.getTableNames(dataPath);
    int len1 = alltbname.size();
    for(int i=0;i<len1;i++){
        printf(" %s",alltbname[i].c_str());
    }
    if(len1 == 0) printf("Nothing...");
    printf("\n");

    //展示所有的用户定义视图
    printf("View Defined By User:");
    std::vector<std::string> allview = sys_ViewKeeper.getAllViewInfo();
    int len2 = allview.size();
    for(int i=0;i<len2;i++){
        printf(" %s",allview[i].c_str());
    }
    if(len2 == 0) printf("Nothing...");
    printf("\n");

    //展示所有的用户定义索引
    printf("Index Defined By User:");
    std::vector<std::vector<std::string> > allindex = sys_IndexKeeper.getAllIndex();
    int len3 = allindex.size();
    for(int i=1;len3>1&&i<len3;i++){
        printf(" %s",allindex[i][0].c_str());
    }
    if(len3 == 0) printf("Nothing...");
    printf("\n");
}

//help_OneDataBase
void help_OneDataBase(const std::string tbname){
    getTableInfo(tbname);
}

//help_OneDataBase
void help_OneView(const std::string tbname){
    // sys_ViewKeeper.getAllViewInfo
    std::vector<std::string> all = sys_ViewKeeper.getAllViewInfo();
    TableUI::TextTable pt;
    if(all.size() == 0){
        pt.Add("Nothing View Defined by User");
        pt.EndOfRow();
        std::cout << pt;
        return;
    }
    pt.Add("Name");
    pt.Add("SQL");
    pt.EndOfRow();
    for(int i=0;i<all.size();i++){
        pt.Add(all[i]);
        pt.Add(sys_ViewKeeper.allview[all[i]]);
        pt.EndOfRow();
    }
    std::cout << pt;
}

//help_OneIndex
void help_OneIndex(const std::string index_name){
    std::vector<std::vector<std::string> > rhs = sys_IndexKeeper.getAllIndex();
    TableUI::TextTable res;
    TableUI::convertTextTable(rhs,res);
    std::cout << res;
}

//验证视图的正确性
//成功1 失败-1
int checkViewSQL(const std::string username,const std::string viewname){
    std::string test_sql = "select * from " + viewname + ";";
    printf("test_view_sql:%s\n",test_sql.c_str());
    sysCheckerCore.check(dataPath,test_sql);
    int test_ret = sysCheckerCore.inner_ret;
    //如果运行错误 则删除视图
    if(test_ret < 0){
        std::string del_sql = "drop view " + viewname + ";";
        printf("del_sql:%s\n",del_sql.c_str());
        sysCheckerCore.check(dataPath,del_sql);
    }
    return test_ret < 0 ? -1 : 1;
}


//获取创建索引的语句中的表名称
//成功0 失败-1
int getTableName_CreateIndex(const std::string line,std::string& tbname){
    std::vector<std::string> res = SavenUtils::RegexSearch(line,"(?<=\\son)\\s+[a-zA-Z0-9\\_]+");
    int lenth = res.size();
    if(lenth <= 0){
        return -1;
    }
    tbname = res[0];
    return 0;
}

//获取删除索引的语句中的表名称
//成功0 失败-1
int getTableName_DropIndex(const std::string line,std::string& tbname){
    //(?<=drop\sindex)\s+[a-zA-Z0-9\_]+
    //获取要删除的索引名称
    std::vector<std::string> res = SavenUtils::RegexSearch(line,"(?<=drop\\sindex)\\s+[a-zA-Z0-9\\_]+");
    int lenth = res.size();
    if(lenth <= 0){
        return -1;
    }
    std::string index_name = res[0];
    //查找该索引所在的基本表
    //vector< vector<string(索引名),string(表名),string(sql语句)> >
    std::vector<std::vector<std::string> > lis = sys_IndexKeeper.getAllIndex();
    lenth = lis.size();
    for(int i=0;i<lenth;i++){
        std::vector<std::string> one = lis[i];
        int len = one.size();
        if(len < 3)continue;
        if(one[0] == index_name){
            tbname = one[1];
            return 0;
        }
    }
    //没有找到
    return -1;
}

// //获取系统文件中的所有表名称
// int getAllTableName(std::vector<std::string>& lis){
//     //
// }


//删除系统中所有无效的视图
std::vector< std::pair<std::string,std::string> > delAllInVaildView(){
    std::vector< std::pair<std::string,std::string> > ans;
    //获取所有视图的名称
    std::vector<std::string> all = sys_ViewKeeper.getAllViewInfo();
    //以此运行各个视图的select信息
    const std::string pre_sql = "select * from ";
    //需要验证是否有权限访问该视图
    int lenth = all.size();
    for(int i=0;i<lenth;i++){
        std::string one = all[i];//遍历视图名称
        printf("[view-check] view check: %s\n",one.c_str());
        if(sys_ViewKeeper.hasView(one) == 0)continue;
        if(sys_UserChecker.admit(cur_user,one,"select")){
            //运行select命令
            sysCheckerCore.check(dataPath,pre_sql + one + ";");
            int ret = sysCheckerCore.inner_ret;
            printf("[view-check] check ret = %d\n",ret);
            if(ret < 0){
                //如果出错
                // if(sysCheckerCore.errMsg)
                std::string line = SavenUtils::StringtoLower(sysCheckerCore.errMsg);
                printf("[view check] check errmsg [%s]\n",line.c_str());
                if(line.find("no such table") == line.npos) continue;
                printf("[view-check] check out for \"no such table\"\n");
                //删除该表
                if(sys_UserChecker.admit(cur_user,one,"drop")){
                    printf("[view-check] permit drop right\n");
                    //删除视图本体
                    std::string del_sql = "drop view ";
                    sysCheckerCore.check(dataPath,del_sql+one+";");
                    //获取视图的sql信息
                    std::string sql_line = sys_ViewKeeper.allview[one];
                    //允许删除该视图
                    sys_ViewKeeper.delView(one);
                    //记录被删除的信息
                    ans.push_back(std::make_pair(one,sql_line));
                    //输出被删除信息
                    printf("[sys] del one view: %s\n",one.c_str());
                }
            }//if
        }//if
    }//for
    return ans;
}


